
#include <iostream>
#include "ufl.h"

using namespace ufl;
using namespace std;

// ’Î∂‘glfwµƒ¥ÌŒÛªÿµÙ∫Ø ˝
void errorCallBack(int error, const char* description)
{
	std::cerr << "glfw error: " << description << std::endl;
}

UFLWindow::UFLWindow(const string& caption, const unsigned int w, const unsigned int h)
:_window(nullptr)
{
	glfwSetErrorCallback(errorCallBack);
	if (!glfwInit()){
		return;
	}
	
	configOpenGLContext();

	_window = glfwCreateWindow(w, h, caption.c_str(), NULL, NULL);
	if (!_window) {
		return;
	}

	makeOpenGLContext();

#ifdef _WIN32
	GLenum glewInitResult = glewInit();
	if (glewInitResult != GLEW_OK) {
		std::cerr << "glew error: " << glewGetErrorString(glewInitResult) << std::endl;
		return;
	}
#endif

	// 打印OpenGL信息
	toolkit::dumpGLInfo();

	// 注册设备响应回调事件
	glfwSetFramebufferSizeCallback(_window, frameBufferSizeCallback);
	glfwSetKeyCallback(_window, keyCallback);
	glfwSetCursorEnterCallback(_window, mouseEnterCallback);
	glfwSetMouseButtonCallback(_window, mouseButtonCallback);
	glfwSetCursorPosCallback(_window, mousePosCallback);
}

UFLWindow::~UFLWindow()
{
	if (_window) {
		glfwDestroyWindow(_window);
	}
}

void UFLWindow::configOpenGLContext()
{
#ifdef __APPLE_CC__
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
}

void UFLWindow::makeOpenGLContext()
{
	if (_window) {
		glfwMakeContextCurrent(_window);
	}
}

ufl_vertex_2i UFLWindow::getWindowPos() const
{
	int x, y;
	glfwGetWindowPos(_window, &x, &y);
	return ufl_vertex_2i(x, y);
}

void UFLWindow::setWindowPos(const ufl_vertex_2i& pos)
{
	glfwSetWindowPos(_window, pos.x, pos.y);
}

void UFLWindow::setWindowCaption(const string& caption)
{
	return glfwSetWindowTitle(_window, caption.c_str());
}

int UFLWindow::mainLoop()
{
	// enter main loop
	UFLRenderer* renderer = UFLGlobalEnvironment::getEnvironment()->getRenderer();
	UFLTimer* timer = UFLGlobalEnvironment::getEnvironment()->getTimer();
	timer->reset();
	if (renderer) {
		
		while (!glfwWindowShouldClose(_window))
		{
			glfwPollEvents();
        
			timer->tick();
            
			renderer->preRender();
			renderer->render();
			renderer->lostRender();

			glfwSwapBuffers(_window);
		}
	}
	
	UFLGlobalEnvironment::destroyEnvironment();
	return 0;
}
